package com.wql.validate;

import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Properties;

/**
 * 身份证校验器
 * 
 * @author wuqinglong
 * @time 2013年11月4日 下午12:43:41
 * @email hellowql@126.com
 * 
 */
public class IdCardValidate {

	private IdCardValidate() {
	}

	private static final int[] ID_CARD_WEIGHT = new int[] { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1 };
	private static final String[] ID_CARD_CHECK = "1,0,X,9,8,7,6,5,4,3,2".split(",");
	private static final String ID_CARD_LETTER_REG = "^\\d{15}$|^\\d{17}[xX]$";
	private static final int ID_CARD_CHECK_LEN = ID_CARD_CHECK.length;
	private static final int MAX_IDCARD_LEN = 18;
	private static final int MIN_IDCARD_LEN = 15;
	private static final Properties props = new Properties();

	static {
		ClassLoader cl = Thread.currentThread().getContextClassLoader();
		InputStream is = cl.getResourceAsStream("com/wql/sources/areaCode.properties");
		try {
			props.load(is);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 是否是身份证
	 * 
	 * @param id
	 * @return
	 */
	public static boolean valid(String id) {
		boolean isCard = Boolean.FALSE;
		int length = length(id);
		if (length != MIN_IDCARD_LEN && length != MAX_IDCARD_LEN || !id.matches(ID_CARD_LETTER_REG)) {
			return isCard;
		}
		int sum = 0;
		if (length == MAX_IDCARD_LEN) {
			if (dateStr(id.substring(6, 14))) {// 6-13位为出生日期
				for (int i = 0, j = MAX_IDCARD_LEN - 1; i < j; i++) {
					sum += Integer.parseInt(id.substring(i, i + 1)) * ID_CARD_WEIGHT[i];
				}
				isCard = ID_CARD_CHECK[sum % ID_CARD_CHECK_LEN].equalsIgnoreCase(id.substring(length - 1));
			}
		} else if (length == MIN_IDCARD_LEN) {
			isCard = dateStr("19" + id.substring(6, 12));// 6-11位为出生日期
		}
		isCard = isCard && null != props.get(id.substring(0, 6));
		return isCard;
	}

	// 字符串是否是日期
	private static boolean dateStr(String str) {
		// String eL = "^(?:([0-9]{4}-(?:(?:0?[1,3-9]|1[0-2])-(?:29|30)|" +
		// "((?:0?[13578]|1[02])-31)))|"
		// + "([0-9]{4}-(?:0?[1-9]|1[0-2])-(?:0?[1-9]|1\\d|2[0-8]))|"
		// + "(((?:(\\d\\d(?:0[48]|[2468][048]|[13579][26]))|"
		// + "(?:0[48]00|[2468][048]00|[13579][26]00))-0?2-29)))$";
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		try {
			return str.equals(sdf.format(sdf.parse(str)));
		} catch (ParseException e) {
		}
		return false;
	}

	// 字符串长度
	private static int length(String str) {
		return str == null ? 0 : str.length();
	}

}
